package com.wili.extract_srcFile.java;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.util.regex.Matcher;
import com.c.Ca;
import com.wili.autoeq.Refs;
import com.wili.autoeq.ValNode;
import com.wili.c.Str9;
/**
 * Serializable Method | Constructor object. 有行号、起止位置信息。
 * @author weila 2021年2月14日
 */
public class MethodRange extends ClsMemberRange implements Comparable<MethodRange> {
	private static final long serialVersionUID = 1L;

	public boolean deepVisited = false;

	public final Class<?> cls;

	public String name;

	public boolean isMethod;

	public Class<?>[] paramTypes;

	public String key;

	transient Executable method;
	{
		if (aId == 1992)
			Ca.pause();
	}

	Exception err;
	/**
	 * 	无参构造且未明示在源码中
	 */
	public static MethodRange newMethodRange(ClsRange range) {
		//Constructor<?>[] cc = range.cls.getDeclaredConstructors();
		try {
			Constructor<?> cons = range.cls.getDeclaredConstructor();
			return new MethodRange(range, cons);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 	无参构造且未明示在源码中? 意义是？
	 */
	private MethodRange(ClsRange range, Constructor<?> cons) {
		super(range, range.aLineNo, range.aStart);
		this.cls = range.cls;
		this.isMethod = false;
		this.method = cons;
		this.name = range.clsName;
	}
	public String[] typeNames, varNames;

	boolean isMe = false;
	/**
	 *  ...In {@link ClsRange#getDeclaredMethodMap()}, will set Method by this. typeName.
	 */
	public MethodRange(RootOfClsMember root, Class<?> cls, Matcher mat, int group, String paramsSt) {
		super(root, mat);
		if (Boolean.FALSE) {
			new ClsRange(null, null, null, "", -1).getDeclaredMethodMap();//在此设 paramTypes
		}
		this.msg = "from_regexp";
		++inc;
		this.cls = cls;
		this.name = mat.group(group);
		if (this.name.equals("log"))
			Ca.pause();
		this.isMethod = !cls.getSimpleName().equals(this.name);
		if (name.equals("MissingLVException")) {
			if (cls.equals(ValNode.class))
				Ca.pause();
			isMe = true;
			System.out.println(inc + ",id" + this.aId + ",MethodRange:" + cls.getName());//10120
			Ca.pause();
		}
		Ca.asert(paramsSt.startsWith("(") && paramsSt.endsWith(")"), paramsSt);
		String[][] namess = Str9.getParamTypeNames_and_varNames(paramsSt.substring(1, paramsSt.length() - 1));
		this.typeNames = namess[0];
		this.varNames = namess[1];
		if (cls.getName().contains("ObjMatcher"))
			if (name.equals("matches"))
				Ca.pause();
	}
	//	public MethodRange(ClsMemberNestedRange root, int lineNo, Executable md) {
	//		super(root);
	//		this.lineNo = lineNo;
	//		this.name = md.getName();
	//		this.paramTypes = md.getParameterTypes();
	//		this.key = md.toString();
	//		msg = "from_javaassist";
	//		if (name.equals("Node"))
	//			Ca.pause();
	//	}

	/**
	 *	for searh in list. 
	 */
	public MethodRange(int lineNo) {
		super(lineNo);
		this.cls = null;
		key = null;
	}

	public void setMethod(Executable md) {
		if (md == null) {
			Refs.ref();
			return;
		}
		if (isMe)
			Ca.pause();
		this.paramTypes = md.getParameterTypes();
		this.name = md.getName();
		this.key = md.toString();
		//this.cls = md.getDeclaringClass();
		Ca.asert(this.cls.equals(md.getDeclaringClass()), md);
		this.method = md;
		if (name.equals("ands"))
			if (cls.getName().equals("wili.autoeq.antlr.DeductParser$ands_return"))
				Ca.pause();
	}
	static int inc;
	@Override
	public int compareTo(MethodRange o) {
		return this.aLineNo - o.aLineNo;
	}
}